package com.zam.web.sysController;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.Quarter;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.auth0.jwt.JWT;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zam.comment.Constants;
import com.zam.comment.Result;
import com.zam.mapper.SysFileMapper;
import com.zam.mapper.UserMapper;
import com.zam.pojo.SysFile;
import com.zam.pojo.User;
import com.zam.pojo.UserExtend;
import com.zam.service.ISysFileService;
import com.zam.service.IUserExtendService;
import com.zam.service.UserService;
import com.zam.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.zam.comment.Constants.CODE_400;
import static com.zam.comment.Constants.USER_NEWS_KEY;

/******************************
 controller层
 ******************************/

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserServiceImpl userService;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ISysFileService sysFileService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private IUserExtendService userExtendService;


    //删除数据
    @DeleteMapping("/{id}")
    public Result delete(@PathVariable int id) {
        userExtendService.removeById(id);
        return Result.success(userService.removeById(id));
    }

    //删除多个
    @DeleteMapping("/batch")
    public Result deleteBatch(@RequestBody List<Integer> ids) {
        userExtendService.removeBatchByIds(ids);
        return Result.success(userService.removeBatchByIds(ids));
    }

    //添加数据、修改数据
    @PostMapping
    public Result add(@RequestBody User user) {
//        System.out.println(user.getId());
        if (user.getId() == null) {
            user.setCreateTime(new Date());
            return Result.success(userService.save(user));
        } else {
            User byId = userService.getById(user.getId());
            if (byId.getAvatar()!=null){
                user.setAvatar(byId.getAvatar());
            }
            return Result.success(userService.updateById(user));
        }
    }

    //修改头像
    @PostMapping("/avatar")
    public Result modifyAvatar(@RequestParam MultipartFile file, HttpServletRequest request) throws IOException {
        //获取token，当Redis中的key
        String token = request.getHeader("token");
        String userIdStr = JWT.decode(token).getAudience().get(0);
        int userId = Integer.parseInt(userIdStr);

        Map<String, Object> map = sysFileService.saveFile(file, request);
        String url = (String) map.get("url");

        System.out.println(url);

        LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(User::getId, userId);
        lambdaUpdateWrapper.set(User::getAvatar, url);
        userService.update(lambdaUpdateWrapper);

        lambdaUpdateWrapper.eq(User::getId, userId);

        User user = userService.getById(userId);
        userService.login(user.getUsername(),user.getPassword());

        return Result.success();
    }

    //分页查询
    @GetMapping("/page")
    public Result limitSelect(int num, int pagesize, User user) {
//        User currentUser = JwtUtil.getCurrentUser();
//        System.out.println("================="+currentUser);
        IPage<User> userPage = new Page<>(num, pagesize);
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (user.getUsername() != null && user.getUsername().isEmpty()) {
            lambdaQueryWrapper.like(User::getUsername, user.getUsername());
        }
        if (user.getEmail() != null && user.getEmail().isEmpty()) {
            lambdaQueryWrapper.like(User::getEmail, user.getEmail());
        }
        if (user.getAddress() != null && user.getAddress().isEmpty()) {
            lambdaQueryWrapper.like(User::getAddress, user.getAddress());
        }
        if (user.getPhone() != null && user.getPhone().isEmpty()) {
            lambdaQueryWrapper.like(User::getPhone, user.getPhone());
        }
        lambdaQueryWrapper.orderByDesc(User::getId);
        return Result.success(userMapper.selectPage(userPage, lambdaQueryWrapper));
    }

    //下载xlsx文件（下载）
    @GetMapping("/download")
    public Result download(HttpServletResponse response) throws IOException {
        List<User> list = userService.list();
        //这个函数将一个List类型的参数list转换为ArrayList类型的对象，并将其赋值给users变量。
        //ArrayList是一种动态数组，它可以在运行时添加或删除元素。
//        ArrayList<User> users = CollUtil.newArrayList(list);
        // 通过工具类创建writer
        //  写到指定位置上
//        ExcelWriter writer = ExcelUtil.getWriter("d:/writeBeanTest.xlsx");
        //先不指定下载位置，以便于生成在浏览器中
        //创建xlsx格式的
        ExcelWriter writer = ExcelUtil.getWriter(true);
        // 自定义标题名称
//        writer.addHeaderAlias("id", "编号");
        writer.addHeaderAlias("username", "姓名");
        writer.addHeaderAlias("password", "密码");
        writer.addHeaderAlias("nickname", "别名");
        writer.addHeaderAlias("email", "邮箱");
        writer.addHeaderAlias("phone", "手机号");
        writer.addHeaderAlias("address", "地址");
        writer.addHeaderAlias("createTime", "创建事件");
        // 默认的，未添加alias的属性也会写出，如果想只写出加了别名的字段，可以调用此方法排除之
        writer.setOnlyAlias(true);
        // 一次性写出内容，使用默认样式，并输出标题
        writer.write(list, true);

        //response为HttpServletResponse对象
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        //编写文件格式
        String filename = URLEncoder.encode("用户信息", "UTF-8");
        //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
        response.setHeader("Content-Disposition", "attachment;filename=" + filename + ".xlsx");

        //获取输出流
        ServletOutputStream out = response.getOutputStream();
        //写出文件
        writer.flush(out, true);
        //关闭输出流
        out.close();
        // 关闭writer，释放内存
        writer.close();
        return Result.success();
    }

    //导入
    @PostMapping("/import")
    public Result importExcel(MultipartFile file) throws IOException {
        //创建流对象
        InputStream inputStream = file.getInputStream();
        //ExcelReader对象
        ExcelReader reader = ExcelUtil.getReader(inputStream);
        //设置表头别名(改为数据库中对应的字段名)
        reader.addHeaderAlias("姓名", "username");
        reader.addHeaderAlias("密码", "password");
        reader.addHeaderAlias("别名", "nickname");
        reader.addHeaderAlias("邮箱", "email");
        reader.addHeaderAlias("手机号", "phone");
        reader.addHeaderAlias("地址", "address");
        reader.addHeaderAlias("创建事件", "create_time");
        List<User> users = reader.readAll(User.class);
        //存入数据库
        userService.saveBatch(users);

        return Result.success();
    }

    //密码验证，登陆
    @PostMapping("/login")
    public Result login(@RequestBody User user, @RequestParam("key") String captchaKey) {
        //验证码校验
        String captcha = stringRedisTemplate.opsForValue().get(captchaKey);
        stringRedisTemplate.delete(captchaKey);
        if (captcha == null || !captcha.equals(user.getCaptcha())) {
            return Result.error(Constants.CODE_400, "验证码错误");
        }

        String username = user.getUsername();
        String password = user.getPassword();
        //验证用户名和密码是否为空
        if (StrUtil.isBlank(username) || StrUtil.isBlank(password)) {
            return Result.error(Constants.CODE_400, "用户名或密码不能为空");
        }
        User loginUser = userService.login(username, password);
        if (BeanUtil.isEmpty(loginUser)) {
            return Result.error(Constants.CODE_400, "用户名或密码错误");
        }
        return Result.success(loginUser);
    }

    //注册
    @PostMapping("/register")
    public Result register(@RequestBody User user) {
        String username = user.getUsername();
        String password = user.getPassword();
        if (StrUtil.isBlank(username) || StrUtil.isBlank(password)) {
            return Result.error(Constants.CODE_400, "用户名或密码不能为空");
        }
        if (userService.count(new LambdaQueryWrapper<User>().eq(User::getUsername, username)) > 0) {
            return Result.error(Constants.CODE_400, "用户名已存在");
        }
        //保存数据到数据库中
        userService.save(user);

        //设置默认积分，默认积分为20
        UserExtend userExtend = new UserExtend();
        userExtend.setUserId(20);
        userExtendService.save(userExtend);

        return Result.success();

    }

    //根据季度统计会员人数的数量
    @GetMapping("/count")
    public Result count() {
        List<User> list = userService.list();
        Integer quarter1 = 0;
        Integer quarter2 = 0;
        Integer quarter3 = 0;
        Integer quarter4 = 0;

        for (User user : list) {
            Date createTime = user.getCreateTime();
            Quarter quarter = DateUtil.quarterEnum(createTime);
            switch (quarter) {
                case Q1:
                    quarter1++;
                    break;
                case Q2:
                    quarter2++;
                    break;
                case Q3:
                    quarter3++;
                    break;
                case Q4:
                    quarter4++;
                    break;
                default:
                    break;
            }
        }
        return Result.success(CollUtil.newArrayList(quarter1, quarter2, quarter3, quarter4));
    }

    //logout
    @DeleteMapping("/logout")
    public Result logout() {
        Set<String> keys = stringRedisTemplate.keys(USER_NEWS_KEY + "*");
        assert keys != null;
        for (String key : keys) {
            stringRedisTemplate.delete(key);
        }
        return Result.success();
    }
}
